#include "display.h"
#include "../Simulation.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <math.h>
#include <stdio.h>

void glut_reshape(int w, int h);
void glut_idle();
void glut_display();
void glut_special(int key, int x, int y);
void glut_mouse(int button, int state, int x, int y);
void glut_motion(int x, int y);

void glut_init(float R, float G, float B);

/*
 * Geometric functions
 */

/*
void spherical_coordinate(double x, double y, double z, double * r, double * theta, double * phi)
{
  *r = sqrt(x*x + y*y + z*z);
  *theta = acos(z/(*r));
  *phi = atan(y/(*r));
}

void cartesian_coordinates(double r, double theta, double phi, double * x, double *  y, double * z)
{
  *x = r*sin(theta)*cos(phi);
  *y = r*sin(theta)*sin(phi);
  *z = r*cos(theta);
}
*/

void spherical_coordinate(double x, double y, double z, double * r, double * theta, double * phi)
{
  *r = sqrt(x*x + y*y + z*z);
  *theta = acos(z/(*r));
  *phi = atan2(y, x);
}

void cartesian_coordinates(double r, double theta, double phi, double * x, double *  y, double * z)
{
  *x = r*sin(theta)*cos(phi);
  *y = r*sin(theta)*sin(phi);
  *z = r*cos(theta);
}

/*
 * GLUT frontend
 */

float i = 0;
int motion_x = -1, motion_y = -1;
double ex = 0.0, ey = 0.0, ez = 50.0;

void display_init(int * argc, char *argv[])
{
  glutInit(argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

  glutInitWindowSize(1200, 800);
  glutCreateWindow("openGL test");

  glutReshapeFunc(glut_reshape); /* must be AFTER CreateWindow... */
  glutIdleFunc(glut_idle);
  glutDisplayFunc(glut_display);
  glutSpecialFunc(glut_special);
  glutMouseFunc(glut_mouse);
  glutMotionFunc(glut_motion);

  glut_init(0.0,0.0,0.0);
}

void display_loop()
{
  glutMainLoop();
}

void glut_special(int key, int x, int y)
{
/*
  double r, theta, phi;
  spherical_coordinate(ex, ey, ez, &r, &theta, &phi);
    switch (key) {
        case GLUT_KEY_LEFT:
          phi += M_PI/6.0;
        break;
        case GLUT_KEY_RIGHT:
          phi += - M_PI/6.0;
        break;
        case GLUT_KEY_UP:
          theta += M_PI/36.0;
        break;
        case GLUT_KEY_DOWN:
          theta += - M_PI/36.0;
        break;
        default:
        break;
    }
  printf("%g %g %g\n", ex, ey, ez);
  cartesian_coordinates(r, theta, phi, &ex, &ey, &ez);
*/
}

void glut_mouse(int button, int state, int x, int y) 
{
  if (state == GLUT_UP )
  {
    if ( button == 3 ) /* GLUT_WHEEL_UP */
    {
      display_scale *= 1.2; /* Zoom in */
    }
    else if( button == 4 ) /* GLUT_WHEEL_DOWN */
    {
      display_scale *= 0.8; /* Zoom out */
    }
  }
  if(button == 0) /* LEFT CLICK */
  {
    if(state == GLUT_UP)
    {
      motion_x = -1;
      motion_y = -1;
      ex = 0.0, ey = 0.0, ez = 50.0;
    }
    else if(state == GLUT_DOWN)
    {
      motion_x = x;
      motion_y = y;
    }
  }
}

void glut_motion(int x, int y)
{
  double r, theta, phi;
  spherical_coordinate(ex, ey, ez, &r, &theta, &phi);
  theta += - ((double) (x - motion_x))/(M_PI*2.0*200.0);
  phi += ((double) (y - motion_y))/(M_PI*2.0*200.0);
  cartesian_coordinates(r, theta, phi, &ex, &ey, &ez);
  printf("%g %g %g\n", ex, ey, ez);
  glutPostRedisplay();
}

void glut_reshape (int w, int h)
{
  float aspect=(float)w/(float)h;
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(50.0f,aspect,1.0f,500.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void glut_init(float R, float G, float B)
{
  glEnable(GL_DEPTH_TEST);
  glClearColor(R,G,B,1.0f);
}

void glut_idle()
{
  updateSimulation(&simul, ((double) glutGet(GLUT_ELAPSED_TIME)) / 1000.0);
  glutPostRedisplay();
}

void glut_display()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
  unsigned int i;
  double x,y,z;
  for(i = 0; i < simul.particules_num; i++)
  {
    glPushMatrix();
    x = display_scale*simul.particules[i].position.x;
    y = display_scale*simul.particules[i].position.y;
    z = display_scale*simul.particules[i].position.z;
    glTranslatef(x,y,z); 
    glColor4f(1.0f,1.0f,1.0f,1.0f);
    glutSolidSphere(0.25f, 10, 10);
    glPopMatrix();
  }
  
  glLoadIdentity();
  gluLookAt(ex, ey, ez, 0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);

  glutSwapBuffers();
}

